package com.hippy.lib.crash

import android.app.Application
import android.content.Context
import android.os.Process
import kotlin.system.exitProcess

class CrashHandler : Thread.UncaughtExceptionHandler {
    private var mApplication: Application
    private var mNextHandler: Thread.UncaughtExceptionHandler
    private var debug = false

    private constructor(application: Application, debug: Boolean = false) {
        this.mApplication = application
        this.debug = debug
        mNextHandler = Thread.getDefaultUncaughtExceptionHandler()
        check(javaClass.name != mNextHandler.javaClass.name) {
            // 请不要重复注册 Crash 监听
            "are you ok? 请不要重复注册 Crash 监听"
        }
    }

    companion object {
        const val CRASH_FILE_NAME = "crash_file"
        const val KEY_CRASH_TIME = "key_crash_time"
        fun register(application: Application, debug: Boolean = false) {
            Thread.setDefaultUncaughtExceptionHandler(CrashHandler(application, debug))
        }
    }


    override fun uncaughtException(thread: Thread, throwable: Throwable) {
        val sharedPreferences =
            mApplication.getSharedPreferences(CRASH_FILE_NAME, Context.MODE_PRIVATE)
        val currentCrashTime = System.currentTimeMillis()
        val lastCrashTime = sharedPreferences.getLong(KEY_CRASH_TIME, 0)
        // 记录当前崩溃的时间，以便下次崩溃时进行比对
        sharedPreferences.edit().putLong(KEY_CRASH_TIME, currentCrashTime).commit()

        // 致命异常标记：如果上次崩溃的时间距离当前崩溃小于 5 分钟，那么判定为致命异常
        val deadlyCrash = currentCrashTime - lastCrashTime < 1000 * 60 * 5
        if (deadlyCrash || debug) {
            CrashActivity.start(mApplication, throwable)
        } else {
            //重启应用
            RestartActivity.restart(mApplication)
        }

        // 不去触发系统的崩溃处理（com.android.internal.os.RuntimeInit$KillApplicationHandler）
        if (mNextHandler != null && !mNextHandler.javaClass.name.startsWith("com.android.internal.os")) {
            mNextHandler.uncaughtException(thread, throwable)
        }

        // 杀死进程（这个事应该是系统干的，但是它会多弹出一个崩溃对话框，所以需要我们自己手动杀死进程）
        Process.killProcess(Process.myPid())
        exitProcess(10)
    }
}